      1  import java.awt.BorderLayout;

      2  import java.awt.GridLayout;

      3  import java.awt.event.ActionListener;

      4  import java.awt.event.ActionEvent;

      5  import javax.swing.ButtonGroup;

      6  import javax.swing.JButton;

      7  import javax.swing.JCheckBox;

      8  import javax.swing.JComboBox;

      9  import javax.swing.JFrame;

     10  import javax.swing.JPanel;

     11  import javax.swing.JRadioButton;

     12  import javax.swing.JLabel;

     13  import javax.swing.border.EtchedBorder;

     14  import javax.swing.border.TitledBorder;

     15

     16  /**

     17     This frame contains a panel that displays buttons

     18     for a calculator and a panel with a text fields to

     19     specify the result of calculation.

     20  */

     21  public class CalculatorFrame extends JFrame

     22  {

     23     private JLabel display;

     24     private JCheckBox radianCheckBox;

     25     private JRadioButton baseeButton;

     26     private JRadioButton base10Button;

     27     private JRadioButton base2Button;

     28     private JComboBox mathOpCombo;

     29     private JButton mathOpButton;

     30

     31     private double lastValue;

     32     private String lastOperator;

     33     private boolean startNewValue;

     34

     35     private static final int FRAME_WIDTH = 400;

     36     private static final int FRAME_HEIGHT = 300;

     37

     38     public CalculatorFrame()

     39     {

     40        createButtonPanel();

     41        createControlPanel();

     42

     43        display = new JLabel("0");

     44        add(display, BorderLayout.NORTH);

     45

     46        lastValue = 0;

     47        lastOperator = "=";

     48        startNewValue = true;

     49

     50        setSize(FRAME_WIDTH, FRAME_HEIGHT);

     51     }

     52

     53     /**

     54        Creates the control panel with the text field

     55        and buttons on the frame.

     56     */

     57     private void createButtonPanel()

     58     {

     59        JPanel buttonPanel = new JPanel();

     60        buttonPanel.setLayout(new GridLayout(4, 4));

     61

     62        buttonPanel.add(makeDigitButton("7"));

     63        buttonPanel.add(makeDigitButton("8"));

     64        buttonPanel.add(makeDigitButton("9"));

     65        buttonPanel.add(makeOperatorButton("/"));

     66        buttonPanel.add(makeDigitButton("4"));

     67        buttonPanel.add(makeDigitButton("5"));

     68        buttonPanel.add(makeDigitButton("6"));

     69        buttonPanel.add(makeOperatorButton("*"));

     70        buttonPanel.add(makeDigitButton("1"));

     71        buttonPanel.add(makeDigitButton("2"));

     72        buttonPanel.add(makeDigitButton("3"));

     73        buttonPanel.add(makeOperatorButton("-"));

     74        buttonPanel.add(makeDigitButton("0"));

     75        buttonPanel.add(makeDigitButton("."));

     76        buttonPanel.add(makeOperatorButton("="));

     77        buttonPanel.add(makeOperatorButton("+"));

     78

     79        add(buttonPanel, BorderLayout.CENTER);

     80     }

     81

     82     class MathOpListener implements ActionListener

     83     {

     84        public void actionPerformed(ActionEvent event)

     85        {

     86           double value = Double.parseDouble(display.getText());

     87           String mathOp = (String) mathOpCombo.getSelectedItem();

     88

     89           double base = 10;

     90           if (baseeButton.isSelected()) { base = Math.E; }

     91           else if (base2Button.isSelected()) { base = 2; }

     92

     93           boolean radian = radianCheckBox.isSelected();

     94           if (!radian && (mathOp.equals("sin")

     95                 || mathOp.equals("cos") || mathOp.equals("tan")))

     96           {

     97              value = Math.toRadians(value);

     98           }

     99

    100           if (mathOp.equals("sin"))

    101           {

    102              value = Math.sin(value);

    103           }

    104           else if (mathOp.equals("cos"))

    105           {

    106              value = Math.cos(value);

    107           }

    108           else if (mathOp.equals("tan"))

    109           {

    110              value = Math.tan(value);

    111           }

    112           else if (mathOp.equals("log"))

    113           {

    114              value = Math.log(value) / Math.log(base);

    115           }

    116           else if (mathOp.equals("exp"))

    117           {

    118              value = Math.pow(base, value);

    119           }

    120           display.setText("" + value);

    121

    122           startNewValue = true;

    123        }

    124     }

    125

    126     private JPanel createBaseButtons()

    127     {

    128        baseeButton = new JRadioButton("e");

    129        base10Button = new JRadioButton("10");

    130        base2Button = new JRadioButton("2");

    131

    132        baseeButton.setSelected(true);

    133

    134        ButtonGroup group = new ButtonGroup();

    135        group.add(baseeButton);

    136        group.add(base10Button);

    137        group.add(base2Button);

    138

    139        JPanel basePanel = new JPanel();

    140        basePanel.add(baseeButton);

    141        basePanel.add(base10Button);

    142        basePanel.add(base2Button);

    143        basePanel.setBorder(new TitledBorder(new EtchedBorder(), "Base"));

    144

    145        return basePanel;

    146     }

    147

    148     private void createControlPanel()

    149     {

    150        radianCheckBox = new JCheckBox("Radian");

    151        radianCheckBox.setSelected(true);

    152

    153        mathOpCombo = new JComboBox();

    154        mathOpCombo.addItem("sin");

    155        mathOpCombo.addItem("cos");

    156        mathOpCombo.addItem("tan");

    157        mathOpCombo.addItem("log");

    158        mathOpCombo.addItem("exp");

    159

    160        mathOpButton = new JButton("Apply");

    161        mathOpButton.addActionListener(new MathOpListener());

    162

    163        JPanel controlPanel = new JPanel();

    164        controlPanel.add(radianCheckBox);

    165        controlPanel.add(createBaseButtons());

    166        controlPanel.add(mathOpCombo);

    167        controlPanel.add(mathOpButton);

    168

    169        add(controlPanel, BorderLayout.SOUTH);

    170     }

    171

    172     /**

    173        Combines two values with an operator.

    174        @param value1 the first value

    175        @param value2 the second value

    176        @param op an operator (+, -, *, /, or =)

    177     */

    178     public double calculate(double value1, double value2, String op)

    179     {

    180        if (op.equals("+"))

    181        {

    182           return value1 + value2;

    183        }

    184        else if (op.equals("-"))

    185        {

    186           return value1 - value2;

    187        }

    188        else if (op.equals("*"))

    189        {

    190           return value1 * value2;

    191        }

    192        else if (op.equals("/"))

    193        {

    194           return value1 / value2;

    195        }

    196        else // "="

    197        {

    198           return value2;

    199        }

    200     }

    201

    202     class DigitButtonListener implements ActionListener

    203     {

    204        private String digit;

    205

    206        /**

    207           Constructs a listener whose actionPerformed method adds a digit

    208           to the display.

    209           @param aDigit the digit to add

    210        */

    211        public DigitButtonListener(String aDigit)

    212        {

    213           digit = aDigit;

    214        }

    215

    216        public void actionPerformed(ActionEvent event)

    217        {

    218           if (startNewValue)

    219           {

    220              display.setText("");

    221              startNewValue = false;

    222           }

    223           display.setText(display.getText() + digit);

    224        }

    225     }

    226

    227     /**

    228        Makes a button representing a digit of a calculator.

    229        @param digit the digit of the calculator

    230        @return the button of the calculator

    231     */

    232     public JButton makeDigitButton(String digit)

    233     {

    234        JButton button = new JButton(digit);

    235        ActionListener listener = new DigitButtonListener(digit);

    236        button.addActionListener(listener);

    237        return button;

    238     }

    239

    240     class OperatorButtonListener implements ActionListener

    241     {

    242        private String operator;

    243

    244        /**

    245           Constructs a listener whose actionPerformed method

    246           schedules an operator for execution.

    247        */

    248        public OperatorButtonListener(String anOperator)

    249        {

    250           operator = anOperator;

    251        }

    252

    253        public void actionPerformed(ActionEvent event)

    254        {

    255           if (!startNewValue)

    256           {

    257              double value = Double.parseDouble(display.getText());

    258              lastValue = calculate(lastValue, value, lastOperator);

    259              display.setText("" + lastValue);

    260              startNewValue = true;

    261           }

    262

    263           lastOperator = operator;

    264        }

    265     }

    266

    267     /**

    268        Makes a button representing an operator of a calculator.

    269        @param op the operator of the calculator

    270        @return the button of the calculator

    271     */

    272     public JButton makeOperatorButton(String op)

    273     {

    274        JButton button = new JButton(op);

    275        ActionListener listener = new OperatorButtonListener(op);

    276        button.addActionListener(listener);

    277        return button;

    278     }

    279  }